package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {


    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void addCart(Long skuId, String userId, Integer skuNum) {
        String cartKey = getCartKey(userId);

        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(cartKey,skuId.toString());
        if(cartInfo!=null){
            cartInfo.setCartPrice(productFeignClient.getSkuPrice(skuId));
            cartInfo.setUpdateTime(new Date());
            if(cartInfo.getIsChecked()==0){
                cartInfo.setIsChecked(1);
            }
        }else {
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfo = new CartInfo();
            cartInfo.setSkuId(skuId);
            cartInfo.setUserId(userId);
            cartInfo.setCartPrice(productFeignClient.getSkuPrice(skuId));
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfo.setIsChecked(1);
            cartInfo.setSkuName(skuInfo.getSkuName());
            cartInfo.setSkuNum(skuNum);
            cartInfo.setCreateTime(new Date());
            cartInfo.setUpdateTime(new Date());
        }

        redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);


    }

    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }

    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        List<CartInfo> noLoginList = new ArrayList<>();

        //未登录状态
        if(!StringUtils.isEmpty(userTempId)){
            String cartKey = this.getCartKey(userTempId);
            BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
            noLoginList = boundHashOperations.values();
        }
        if(!CollectionUtils.isEmpty(noLoginList) && StringUtils.isEmpty(userId)){
            noLoginList.sort((o1,o2)->{
              return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
            });
            return noLoginList;
        }

        //-------------------------登录状态----------------------------------------
        if(!StringUtils.isEmpty(userId)){
            String cartKey = this.getCartKey(userId);
            BoundHashOperations<String,String,CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);

            List<CartInfo> LoginList = null;

            if(!CollectionUtils.isEmpty(noLoginList)){
                noLoginList.stream().forEach(cartInfoNoLogin ->{
                    if(boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())){
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId());
                        cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum());
                        cartInfoLogin.setUpdateTime(new Date());
                        cartInfoLogin.setSkuPrice(productFeignClient.getSkuPrice(cartInfoNoLogin.getSkuId()));

                        if(cartInfoNoLogin.getIsChecked().intValue()==1 && cartInfoLogin.getIsChecked().intValue()==0){
                            cartInfoLogin.setIsChecked(1);
                        }

                        boundHashOperations.put(cartInfoLogin.getSkuId().toString(),cartInfoLogin);
                    }else {
                        cartInfoNoLogin.setUserId(userId);
                        cartInfoNoLogin.setUpdateTime(new Date());
                        cartInfoNoLogin.setCreateTime(new Date());
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    }
                } );
            }
            redisTemplate.delete(this.getCartKey(userTempId));
            LoginList = boundHashOperations.values();

            //排序
            if(!CollectionUtils.isEmpty(LoginList)){
                LoginList.sort((o1,o2)->{
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(), Calendar.SECOND);
                });
                return LoginList;
            }
            return LoginList;
        }
        return new ArrayList<>();
    }

    @Override
    public void checkCart(String userId, Integer isChecked, Long skuId) {
        String cartKey = this.getCartKey(userId);
        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if(cartInfo!=null){
            cartInfo.setIsChecked(isChecked);
            redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
        }
    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        String cartKey = this.getCartKey(userId);
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(cartKey);
        if(boundHashOperations.hasKey(skuId.toString())){
            boundHashOperations.delete(skuId.toString());
        }
    }

    @Override
    public List<CartInfo> getCheckedCartList(String userId) {
        String cartKey = this.getCartKey(userId);
        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        List<CartInfo> list = cartInfoList.stream().filter(cartInfo -> {
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());
        return list;
    }
}
